<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Fetch 综合案例</title>
</head>
<body>
<h1>用户信息展示</h1>
<form id="loginForm">
    <label for="username">用户名:</label>
    <input type="text" id="username" name="username"><br><br>
    <label for="password">密码:</label>
    <input type="password" id="password" name="password"><br><br>
    <button type="submit">登录</button>
</form>

<div id="userInfo"></div>
<img id="userAvatar" alt="用户头像">

<button type="button" onclick="testLoadAvatar()">测试加载头像</button>
<img id="testAvatar" alt="测试头像">


<script>
    // 登录函数 - 发送 POST 表单数据
    function login(formData) {
        return fetch('https://www.qweather.com/v2/search?lng=undefined&lat=undefined', {
            method: 'POST',
            body: formData,
            credentials: 'include' // 允许跨域携带 cookies
            //🔐 场景一：用户登录后维持会话（Session）
            //当你使用 Cookie + Session 的方式实现登录状态时，服务器会在登录成功后设置一个 Set-Cookie，后续请求需要带上这个 Cookie 才能识别用户身份。
            //如果不加 credentials: 'include'，即使服务端设置了 Cookie，浏览器也不会在后续请求中自动携带它。

            //用法
            //                           是否跨域可用   是否携带 Cookie
            //credentials: 'omit'           ❌
            //credentials: 'same-origin'✅（仅限同源）  ✅（同源时）
            //credentials: 'include'    ✅（支持跨域）  ✅（包括跨域）
        }).catch(error => {  //这里如果抛出错误的额话控制台就是 也会有这个错误的抛出，会有两个错误的提示
            console.error('请求出错！！！:', error);
            throw error; // 继续抛出错误，让外层 catch 捕获
        });
    }

    // 获取用户信息 - GET 请求 + 自定义 headers
    function fetchUserInfo(userId, token) {
        return fetch(`https://api.example.com/users/${userId}`, {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${token}`
            },
            credentials: 'include'
        });
    }

    // 获取用户头像 - 使用 Request 和 Response 对象
    function fetchUserAvatar(url) {
        const request = new Request(url);
        return fetch(request).then(response => response.blob());//Blob 表示“二进制大对象”（Binary Large Object），可以用来表示图片、音频、视频、文件等原始二进制数据。
    }

    //https://www.baidu.com/s?wd=%E7%99%BE%E5%BA%A6%E7%83%AD%E6%90%9C&sa=ire_dl_gh_logo_texing&rsv_dl=igh_logo_pc
    function testLoadAvatar() {
        const imageUrl = 'https://picsum.photos/200/300'; // 替换为你想测试的图片地址
        fetch(imageUrl)
            .then(response => response.blob())
            .then(blob => {
                const url = URL.createObjectURL(blob);  //！！！这样子加载出来的图片的地址src是自己的前端页面的 地址，不是图片的真实地址
                document.getElementById('testAvatar').src = url;
            })
            .catch(error => console.error('加载图片失败:', error));
    }


    // 监听登录表单提交事件
    document.getElementById('loginForm').addEventListener('submit', async function (e) {
        e.preventDefault();

        const username = document.getElementById('username').value;
        const password = document.getElementById('password').value;

        const formData = new FormData();
        formData.append('username', username);
        formData.append('password', password);

        try {
            // Step 1: 登录并获取 token
            const loginResponse = await login(formData);
            if (!loginResponse.ok) {  //如果是链接的网络的错误的话这里不会有接收 到的json数据，从而也不会将下面的错误信息抛出到catch，这里会直接将promise中的 错误信息抛出到catch
                throw new Error('登录失败');  // 抛出异常，让外层 catch 捕获
            }
            const loginData = await loginResponse.json();
            const token = loginData.token;

            // Step 2: 使用 token 获取用户信息
            const userResponse = await fetchUserInfo(loginData.userId, token);
            if (!userResponse.ok) {
                throw new Error(`获取用户信息失败: ${userResponse.statusText}`);
            }
            const userData = await userResponse.json();
            document.getElementById('userInfo').innerText = JSON.stringify(userData, null, 2);

            // Step 3: 获取用户头像并显示
            const avatarBlob = await fetchUserAvatar(userData.avatarUrl);
            const avatarUrl = URL.createObjectURL(avatarBlob);
            document.getElementById('userAvatar').src = avatarUrl;

        } catch (error) {
            console.error('请求出错:', error);
            alert('操作失败，请查看控制台日志。'+ error);
        }
    });
</script>
</body>
</html>
